<script setup>
import { ref, onMounted, watch } from "vue";
import { isTrue } from "../../lib";
import { Search } from "@element-plus/icons-vue";
const searchWord = ref("");
const props = defineProps({
  data: {
    type: Array,
    default: () => {
      return [];
    },
  },
  // 父子是否互相关联
  checkStrictly: {
    type: Boolean,
    default: false,
  },
  // 默认选择的菜单项标识
  modelValue: {
    type: Array,
    default: () => {
      return [];
    },
  },
  // 自定义配置属性
  defaultProps: {
    type: Object,
    default: () => {
      return { children: "children", label: "name" };
    },
  },
  // 是否显示搜索项
  showSearch: {
    type: Boolean,
    default: false,
  },
});
const emits = defineEmits(["update:modelValue"]);
const checkedKeys = ref(props.modelValue);
const treeRef = ref(null);

watch(searchWord, (val) => {
  treeRef.value.filter(val);
});

/**
 * 初始化选择的节点，处理父节点为半选状态
 */
const initCheck = (functionIdList) => {
  treeRef.value.setCheckedKeys([]);
  functionIdList.forEach((i) => {
    // 根据id 拿到 Tree 组件中的node的所有信息
    let node = treeRef.value.getNode(i);
    // node.isLeaf：判断当前节点是否为子节点
    if (node.isLeaf) {
      //如果是子节点，就把状态设置成选中
      treeRef.value.setChecked(node, true);
    }
  });
};

/**
 * 触发多选框事件
 */
const checkChange = () => {
  const keys = treeRef.value.getCheckedKeys();
  const parentKeys = treeRef.value.getHalfCheckedKeys();
  const nodes = keys.concat(parentKeys);
  emits("update:modelValue", nodes);
};

const getFlatList = (treeData, child, arr) => {
  treeData.forEach((item) => {
    arr.push(item.id);
    if (item[child] && item[child].length > 0) {
      getFlatList(item[child], child, arr);
    }
  });
  return arr;
};

/**
 * 手动处理节点取消选中
 */
const hanleCheck = (data) => {
  if (!props.checkStrictly) return;
  let checkNode = treeRef.value.getNode(data);
  if (!checkNode.data.children) return;
  // 全选反选所有子节点
  const menuArr = getFlatList(checkNode.data.children, "children", []);
  menuArr.forEach((item) => {
    treeRef.value.setChecked(item, checkNode.checked);
  });
  // 如果子节点选中，所有父节点默认选中
  let firstParentId = "";
  const parentId = checkNode.parent.data.id;
  if (checkNode.level === 3) {
    firstParentId = checkNode.parent.parent.data.id;
  }
  if (checkNode.checked) {
    treeRef.value.setChecked(parentId, checkNode.checked);
    treeRef.value.setChecked(firstParentId, checkNode.checked);
  }
  // 二级菜单全部取消时，一级菜单也要取消
  if (checkNode.level === 2 && !checkNode.checked) {
    const menuId = checkNode.parent.data.children.map((item) => item.id);
    const keys = treeRef.value.getCheckedKeys();
    if (!keys.some((item) => menuId.includes(item))) {
      treeRef.value.setChecked(parentId, checkNode.checked);
    }
  }
};

/**
 * 搜索节点
 */
const filterNode = (value, data, node) => {
  if (!value) return true;
  let parentNode = node.parent,
    labels = [node.label],
    level = 1;
  while (level < node.level) {
    labels = [...labels, parentNode.label];
    parentNode = parentNode.parent;
    level++;
  }
  return labels.some((label) => label.indexOf(value) !== -1);
};

/**
 * 初始化数据
 */
onMounted(() => {
  if (!props.checkStrictly) initCheck(props.modelValue);
});
</script>
<template>
  <el-input
    v-if="showSearch"
    style="width: 200px; padding: 10px 0"
    v-model="searchWord"
    placeholder="请输入关键字"
    :prefix-icon="Search"
  />
  <el-tree
    v-bind="$attrs"
    ref="treeRef"
    :data="data"
    :check-strictly="checkStrictly"
    :node-key="$attrs.nodeKey || 'id'"
    default-expand-all
    :default-checked-keys="checkedKeys"
    :expand-on-click-node="false"
    :props="defaultProps"
    @check="hanleCheck"
    @check-change="checkChange"
    :filter-node-method="filterNode"
  />
</template>
